mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-22 06:17:47 +00:00
Get selected nodes
This commit is contained in:
parent
bfe6613871
commit
3d25633a38
@ -5,16 +5,30 @@ import {SVGSelection} from "../../../map/models/types";
|
|||||||
import {Node} from "../models/node.model";
|
import {Node} from "../models/node.model";
|
||||||
|
|
||||||
|
|
||||||
|
class OnSelectedListenerMock {
|
||||||
|
public constructor(public nodes: Node[] = []) {}
|
||||||
|
|
||||||
|
public listen(nodes: Node[]) {
|
||||||
|
console.log(this);
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('SelectionTool', () => {
|
describe('SelectionTool', () => {
|
||||||
let tool: SelectionTool;
|
let tool: SelectionTool;
|
||||||
let svg: SVGSelection;
|
let svg: SVGSelection;
|
||||||
let context: Context;
|
let context: Context;
|
||||||
let selection_line_tool: SVGSelection;
|
let selection_line_tool: SVGSelection;
|
||||||
let path_selection: SVGSelection;
|
let path_selection: SVGSelection;
|
||||||
|
let selected_nodes: Node[];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tool = new SelectionTool();
|
tool = new SelectionTool();
|
||||||
|
|
||||||
|
tool.selectedSubject.subscribe((nodes: Node[]) => {
|
||||||
|
selected_nodes = nodes;
|
||||||
|
});
|
||||||
|
|
||||||
svg = select('body')
|
svg = select('body')
|
||||||
.append<SVGSVGElement>('svg')
|
.append<SVGSVGElement>('svg')
|
||||||
.attr('width', 1000)
|
.attr('width', 1000)
|
||||||
@ -95,14 +109,23 @@ describe('SelectionTool', () => {
|
|||||||
expect(svg.select('.selected').datum().name).toEqual("Node 1");
|
expect(svg.select('.selected').datum().name).toEqual("Node 1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('selectedSubject should update nodes', () => {
|
||||||
|
expect(selected_nodes.length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
describe('SelectionTool can deselect after click outside', () => {
|
describe('SelectionTool can deselect after click outside', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 300, clientY: 300}));
|
svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 300, clientY: 300}));
|
||||||
|
window.dispatchEvent(new MouseEvent('mouseup', {clientX: 300, clientY: 300}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have no selection', () => {
|
it('should have no selection', () => {
|
||||||
expect(svg.selectAll('.selected').size()).toEqual(0);
|
expect(svg.selectAll('.selected').size()).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('selectedSubject should clear nodes', () => {
|
||||||
|
expect(selected_nodes.length).toEqual(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -2,12 +2,20 @@ import {SVGSelection} from "../../../map/models/types";
|
|||||||
import {mouse, select} from "d3-selection";
|
import {mouse, select} from "d3-selection";
|
||||||
import {Context} from "../../../map/models/context";
|
import {Context} from "../../../map/models/context";
|
||||||
import {Node} from "../models/node.model";
|
import {Node} from "../models/node.model";
|
||||||
|
import {Subject} from "rxjs/Subject";
|
||||||
|
|
||||||
|
|
||||||
export class SelectionTool {
|
export class SelectionTool {
|
||||||
|
static readonly SELECTABLE_CLASS = '.selectable';
|
||||||
|
|
||||||
private selection: SVGSelection;
|
private selection: SVGSelection;
|
||||||
private path;
|
private path;
|
||||||
private context: Context;
|
private context: Context;
|
||||||
|
public selectedSubject: Subject<Node[]>;
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
this.selectedSubject = new Subject<Node[]>();
|
||||||
|
}
|
||||||
|
|
||||||
public connect(selection: SVGSelection, context: Context) {
|
public connect(selection: SVGSelection, context: Context) {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
@ -31,26 +39,17 @@ export class SelectionTool {
|
|||||||
self.startSelection(start);
|
self.startSelection(start);
|
||||||
|
|
||||||
// clear selection
|
// clear selection
|
||||||
self.selection.selectAll('.selectable').classed("selected", false);
|
self.selection
|
||||||
|
.selectAll(SelectionTool.SELECTABLE_CLASS)
|
||||||
|
.classed("selected", false);
|
||||||
|
|
||||||
subject
|
subject
|
||||||
.on("mousemove.selection", function() {
|
.on("mousemove.selection", function() {
|
||||||
const end = transformation(mouse(parent));
|
const end = transformation(mouse(parent));
|
||||||
self.moveSelection(start, end);
|
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() {
|
}).on("mouseup.selection", function() {
|
||||||
self.endSelection(start, transformation(mouse(parent)));
|
const end = transformation(mouse(parent));
|
||||||
|
self.endSelection(start, end);
|
||||||
subject
|
subject
|
||||||
.on("mousemove.selection", null)
|
.on("mousemove.selection", null)
|
||||||
.on("mouseup.selection", null);
|
.on("mouseup.selection", null);
|
||||||
@ -85,10 +84,33 @@ export class SelectionTool {
|
|||||||
|
|
||||||
private moveSelection(start, move) {
|
private moveSelection(start, move) {
|
||||||
this.path.attr("d", this.rect(start[0], start[1], move[0] - start[0], move[1] - start[1]));
|
this.path.attr("d", this.rect(start[0], start[1], move[0] - start[0], move[1] - start[1]));
|
||||||
|
this.getSelectedNodes(start, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
private endSelection(start, end) {
|
private endSelection(start, end) {
|
||||||
this.path.attr("visibility", "hidden");
|
this.path.attr("visibility", "hidden");
|
||||||
|
const selected_nodes = this.getSelectedNodes(start, end);
|
||||||
|
this.selectedSubject.next(selected_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSelectedNodes(start, end): Node[] {
|
||||||
|
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]);
|
||||||
|
const nodes: Node[] = [];
|
||||||
|
|
||||||
|
this.selection
|
||||||
|
.selectAll(SelectionTool.SELECTABLE_CLASS)
|
||||||
|
.classed('selected', (node: Node) => {
|
||||||
|
const in_rect = (x <= node.x && node.x < (x + width) && y <= node.y && node.y < (y + height));
|
||||||
|
if (in_rect) {
|
||||||
|
nodes.push(node);
|
||||||
|
}
|
||||||
|
return in_rect;
|
||||||
|
});
|
||||||
|
|
||||||
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private rect(x: number, y: number, w: number, h: number) {
|
private rect(x: number, y: number, w: number, h: number) {
|
||||||
|
@ -47,6 +47,10 @@ svg image:hover, svg image.chosen, .selectable.selected {
|
|||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
link.selectable.selected {
|
||||||
|
color: darkred;
|
||||||
|
}
|
||||||
|
|
||||||
.selection-line-tool .selection {
|
.selection-line-tool .selection {
|
||||||
fill: #7ccbe1;
|
fill: #7ccbe1;
|
||||||
stroke: #66aec2 ;
|
stroke: #66aec2 ;
|
||||||
|
Loading…
Reference in New Issue
Block a user