From 3192ce43769a77ca38e8c313966ca48463da4f59 Mon Sep 17 00:00:00 2001 From: ziajka Date: Thu, 15 Mar 2018 15:19:50 +0100 Subject: [PATCH] Graphically select nodes --- .../shared/tools/selection-tool.spec.ts | 45 +++++++++++++++++-- .../shared/tools/selection-tool.ts | 17 ++++++- .../shared/widgets/nodes.widget.ts | 2 +- src/app/project-map/project-map.component.css | 2 +- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/app/cartography/shared/tools/selection-tool.spec.ts b/src/app/cartography/shared/tools/selection-tool.spec.ts index cdd2f975..9c5558d8 100644 --- a/src/app/cartography/shared/tools/selection-tool.spec.ts +++ b/src/app/cartography/shared/tools/selection-tool.spec.ts @@ -2,6 +2,7 @@ import {SelectionTool} from "./selection-tool"; import {select} from "d3-selection"; import {Context} from "../../../map/models/context"; import {SVGSelection} from "../../../map/models/types"; +import {Node} from "../models/node.model"; describe('SelectionTool', () => { @@ -19,6 +20,25 @@ describe('SelectionTool', () => { .attr('width', 1000) .attr('height', 1000); + const node_1 = new Node(); + node_1.name = "Node 1"; + node_1.x = 150; + node_1.y = 150; + + const node_2 = new Node(); + node_2.name = "Node 2"; + node_2.x = 300; + node_2.y = 300; + + svg.selectAll('g.node') + .data([node_1, node_2], (n: Node) => { + return n.node_id; + }) + .enter() + .append('g') + .attr('class', 'node selectable'); + + svg.append('g').attr('class', 'canvas'); context = new Context(); @@ -62,12 +82,30 @@ describe('SelectionTool', () => { describe('SelectionTool can handle end of selection', () => { beforeEach(() => { svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 100, clientY: 100})); - window.dispatchEvent(new MouseEvent('mousemove', {clientX: 300, clientY: 300})); - window.dispatchEvent(new MouseEvent('mouseup', {clientX: 300, clientY: 300})); + window.dispatchEvent(new MouseEvent('mousemove', {clientX: 200, clientY: 200})); + window.dispatchEvent(new MouseEvent('mouseup', {clientX: 200, clientY: 200})); }); it('path should be hidden', () => { - expect(path_selection.attr('visibility')).toEqual('hidden'); + expect(path_selection.attr('visibility')).toEqual('hidden'); + }); + + it('node should be selected', () => { + expect(svg.selectAll('.selected').size()).toEqual(1); + expect(svg.select('.selected').datum().name).toEqual("Node 1"); + }); + }); + + describe('SelectionTool can handle end of selection in reverse direction', () => { + beforeEach(() => { + svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 200, clientY: 200})); + window.dispatchEvent(new MouseEvent('mousemove', {clientX: 100, clientY: 100})); + window.dispatchEvent(new MouseEvent('mouseup', {clientX: 100, clientY: 100})); + }); + + it('node should be selected', () => { + expect() + expect(svg.select('.selected').datum().name).toEqual("Node 1"); }); }); @@ -82,4 +120,5 @@ describe('SelectionTool', () => { }); }); + }); diff --git a/src/app/cartography/shared/tools/selection-tool.ts b/src/app/cartography/shared/tools/selection-tool.ts index fb343908..a43e2f94 100644 --- a/src/app/cartography/shared/tools/selection-tool.ts +++ b/src/app/cartography/shared/tools/selection-tool.ts @@ -1,6 +1,8 @@ import {SVGSelection} from "../../../map/models/types"; import {mouse, select} from "d3-selection"; import {Context} from "../../../map/models/context"; +import {Node} from "../models/node.model"; + export class SelectionTool { private selection: SVGSelection; @@ -30,7 +32,20 @@ export class SelectionTool { subject .on("mousemove.selection", function() { - self.moveSelection(start, transformation(mouse(parent))); + const end = transformation(mouse(parent)); + self.moveSelection(start, end); + + const x = Math.min(start[0], end[0]); + const y = Math.min(start[1], end[1]); + const width = Math.abs(start[0] - end[0]); + const height = Math.abs(start[1] - end[1]); + + self.selection + .selectAll('.selectable') + .classed('selected', (node: Node, i) => { + return (x <= node.x && node.x < (x + width) && y <= node.y && node.y < (y + height)); + }); + }).on("mouseup.selection", function() { self.endSelection(start, transformation(mouse(parent))); subject diff --git a/src/app/cartography/shared/widgets/nodes.widget.ts b/src/app/cartography/shared/widgets/nodes.widget.ts index 1332a21e..0e3dc493 100644 --- a/src/app/cartography/shared/widgets/nodes.widget.ts +++ b/src/app/cartography/shared/widgets/nodes.widget.ts @@ -90,7 +90,7 @@ export class NodesWidget implements Widget { const node_enter = node .enter() .append('g') - .attr('class', 'node'); + .attr('class', 'node selectable'); node_enter .append('image') diff --git a/src/app/project-map/project-map.component.css b/src/app/project-map/project-map.component.css index 547d00e6..5e262453 100644 --- a/src/app/project-map/project-map.component.css +++ b/src/app/project-map/project-map.component.css @@ -43,7 +43,7 @@ g.node text { } -svg image:hover, svg image.chosen { +svg image:hover, svg image.chosen, .selectable.selected { filter: grayscale(100%); }