Merge pull request #553 from GNS3/Snap-to-grid

Snap to grid
This commit is contained in:
piotrpekala7 2019-10-25 10:48:56 +02:00 committed by GitHub
commit 3e54df0b79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 17 deletions

View File

@ -7,6 +7,7 @@ import { DraggedDataEvent } from '../../../cartography/events/event-source';
import { MapDrawing } from '../../../cartography/models/map/map-drawing';
import { Drawing } from '../../../cartography/models/drawing';
import { DrawingsEventSource } from '../../../cartography/events/drawings-event-source';
import { Project } from '../../../models/project';
@Component({
selector: 'app-drawing-dragged',
@ -15,6 +16,7 @@ import { DrawingsEventSource } from '../../../cartography/events/drawings-event-
})
export class DrawingDraggedComponent implements OnInit, OnDestroy {
@Input() server: Server;
@Input() project: Project;
private drawingDragged: Subscription;
constructor(
@ -33,7 +35,7 @@ export class DrawingDraggedComponent implements OnInit, OnDestroy {
drawing.y += draggedEvent.dy;
this.drawingService
.updatePosition(this.server, drawing, drawing.x, drawing.y)
.updatePosition(this.server, this.project, drawing, drawing.x, drawing.y)
.subscribe((serverDrawing: Drawing) => {
this.drawingsDataSource.update(serverDrawing);
});

View File

@ -7,6 +7,7 @@ import { Server } from '../../../models/server';
import { NodesEventSource } from '../../../cartography/events/nodes-event-source';
import { MapNode } from '../../../cartography/models/map/map-node';
import { Subscription } from 'rxjs';
import { Project } from '../../../models/project';
@Component({
selector: 'app-node-dragged',
@ -15,6 +16,7 @@ import { Subscription } from 'rxjs';
})
export class NodeDraggedComponent implements OnInit, OnDestroy {
@Input() server: Server;
@Input() project: Project
private nodeDragged: Subscription;
constructor(
@ -32,7 +34,7 @@ export class NodeDraggedComponent implements OnInit, OnDestroy {
node.x += draggedEvent.dx;
node.y += draggedEvent.dy;
this.nodeService.updatePosition(this.server, node, node.x, node.y).subscribe((serverNode: Node) => {
this.nodeService.updatePosition(this.server, this.project, node, node.x, node.y).subscribe((serverNode: Node) => {
this.nodesDataSource.update(serverNode);
});
}

View File

@ -96,6 +96,9 @@
</mat-checkbox><br/>
<mat-checkbox [ngModel]="gridVisibility" (change)="toggleGrid($event.checked)">
Show grid
</mat-checkbox><br/>
<mat-checkbox [ngModel]="project.snap_to_grid" (change)="toggleSnapToGrid($event.checked)">
Snap to grid
</mat-checkbox>
</div>
</mat-menu>
@ -158,11 +161,11 @@
<app-project-map-shortcuts *ngIf="project" [project]="project" [server]="server"></app-project-map-shortcuts>
<app-draw-link-tool [links]="links" *ngIf="tools.draw_link"></app-draw-link-tool>
<app-drawing-dragged [server]="server"></app-drawing-dragged>
<app-drawing-dragged [server]="server" [project]="project"></app-drawing-dragged>
<app-drawing-resized [server]="server"></app-drawing-resized>
<app-interface-label-dragged [server]="server"></app-interface-label-dragged>
<app-link-created [server]="server" [project]="project"></app-link-created>
<app-node-dragged [server]="server"></app-node-dragged>
<app-node-dragged [server]="server" [project]="project"></app-node-dragged>
<app-node-label-dragged [server]="server"></app-node-label-dragged>
<app-text-added [server]="server" [project]="project" (drawingSaved)="onDrawingSaved()"> </app-text-added>
<app-text-edited [server]="server"></app-text-edited>

View File

@ -144,7 +144,7 @@ export class MockedDrawingService {
return of(drawing);
}
updatePosition(_server: Server, _drawing: Drawing, _x: number, _y: number) {
updatePosition(_server: Server, _project: Project, _drawing: Drawing, _x: number, _y: number) {
return of(this.drawing);
}

View File

@ -504,6 +504,10 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.mapChild.gridVisibility = this.gridVisibility ? 1 : 0;
}
public toggleSnapToGrid(enabled: boolean) {
this.project.snap_to_grid = enabled;
}
private showMessage(msg) {
if (this.notificationsVisibility) {
if (msg.type === 'error') this.toasterService.error(msg.message);

View File

@ -8,17 +8,20 @@ import { Drawing } from '../cartography/models/drawing';
import { getTestServer } from './testing';
import { DrawingService } from './drawing.service';
import { AppTestingModule } from '../testing/app-testing/app-testing.module';
import { Project } from '../models/project';
import { SvgToDrawingConverter } from '../cartography/helpers/svg-to-drawing-converter';
describe('DrawingService', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
let httpServer: HttpServer;
let server: Server;
let project: Project = new Project();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, AppTestingModule],
providers: [HttpServer, DrawingService]
providers: [HttpServer, SvgToDrawingConverter, DrawingService]
});
httpClient = TestBed.get(HttpClient);
@ -40,7 +43,7 @@ describe('DrawingService', () => {
drawing.project_id = 'myproject';
drawing.drawing_id = 'id';
service.updatePosition(server, drawing, 10, 20).subscribe();
service.updatePosition(server, project, drawing, 10, 20).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/drawings/id');
expect(req.request.method).toEqual('PUT');
@ -55,7 +58,7 @@ describe('DrawingService', () => {
drawing.project_id = 'myproject';
drawing.drawing_id = 'id';
service.updatePosition(server, drawing, 10.1, 20.6).subscribe();
service.updatePosition(server, project, drawing, 10.1, 20.6).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/drawings/id');
expect(req.request.method).toEqual('PUT');

View File

@ -5,10 +5,15 @@ import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import { Server } from '../models/server';
import { HttpServer } from './http-server.service';
import { Project } from '../models/project';
import { SvgToDrawingConverter } from '../cartography/helpers/svg-to-drawing-converter';
@Injectable()
export class DrawingService {
constructor(private httpServer: HttpServer) {}
constructor(
private httpServer: HttpServer,
private svgToDrawingConverter: SvgToDrawingConverter
) {}
add(server: Server, project_id: string, x: number, y: number, svg: string) {
return this.httpServer.post<Drawing>(server, `/projects/${project_id}/drawings`, {
@ -29,10 +34,23 @@ export class DrawingService {
});
}
updatePosition(server: Server, drawing: Drawing, x: number, y: number): Observable<Drawing> {
updatePosition(server: Server, project: Project, drawing: Drawing, x: number, y: number): Observable<Drawing> {
let xPosition: number = Math.round(x);
let yPosition: number = Math.round(y);
if (project.snap_to_grid) {
drawing.element = this.svgToDrawingConverter.convert(drawing.svg);
xPosition = Math.round((xPosition + drawing.element.width/2) / project.drawing_grid_size) * project.drawing_grid_size;
yPosition = Math.round((yPosition + drawing.element.width/2) / project.drawing_grid_size) * project.drawing_grid_size;
xPosition = Math.round(xPosition - drawing.element.width/2);
yPosition = Math.round(yPosition - drawing.element.height/2);
}
return this.httpServer.put<Drawing>(server, `/projects/${drawing.project_id}/drawings/${drawing.drawing_id}`, {
x: Math.round(x),
y: Math.round(y)
x: xPosition,
y: yPosition
});
}

View File

@ -154,11 +154,14 @@ describe('NodeService', () => {
}));
it('should updatePosition of node', inject([NodeService], (service: NodeService) => {
let project = {
project_id: '1'
} as Project;
const node = new Node();
node.project_id = 'myproject';
node.node_id = 'id';
service.updatePosition(server, node, 10, 20).subscribe();
service.updatePosition(server, project, node, 10, 20).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/nodes/id');
expect(req.request.method).toEqual('PUT');
@ -169,11 +172,14 @@ describe('NodeService', () => {
}));
it('should updatePosition of node and round to integer', inject([NodeService], (service: NodeService) => {
let project = {
project_id: '1'
} as Project;
const node = new Node();
node.project_id = 'myproject';
node.node_id = 'id';
service.updatePosition(server, node, 10.1, 20.6).subscribe();
service.updatePosition(server, project, node, 10.1, 20.6).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/nodes/id');
expect(req.request.method).toEqual('PUT');

View File

@ -53,10 +53,21 @@ export class NodeService {
});
}
updatePosition(server: Server, node: Node, x: number, y: number): Observable<Node> {
updatePosition(server: Server, project: Project, node: Node, x: number, y: number): Observable<Node> {
let xPosition: number = Math.round(x);
let yPosition: number = Math.round(y);
if (project.snap_to_grid) {
xPosition = Math.round((xPosition + node.width/2) / project.grid_size) * project.grid_size;
yPosition = Math.round((yPosition + node.width/2) / project.grid_size) * project.grid_size;
xPosition = Math.round(xPosition - node.width/2);
yPosition = Math.round(yPosition - node.height/2);
}
return this.httpServer.put<Node>(server, `/projects/${node.project_id}/nodes/${node.node_id}`, {
x: Math.round(x),
y: Math.round(y)
x: xPosition,
y: yPosition
});
}